const { body, param, query, validationResult } = require('express-validator');
const { validationErrorResponse } = require('../utils/response');

/**
 * 处理验证结果中间件
 */
const handleValidationErrors = (req, res, next) => {
  const errors = validationResult(req);
  
  if (!errors.isEmpty()) {
    const formattedErrors = errors.array().map(error => ({
      field: error.path || error.param,
      message: error.msg,
      value: error.value
    }));
    
    console.log('Validation errors:', formattedErrors);
    return validationErrorResponse(res, formattedErrors);
  }
  
  next();
};

/**
 * 用户注册验证规则
 */
const validateUserRegistration = [
  body('username')
    .trim()
    .isLength({ min: 2, max: 50 })
    .withMessage('用户名长度必须在2-50个字符之间')
    .matches(/^[a-zA-Z0-9\u4e00-\u9fa5_-]+$/)
    .withMessage('用户名只能包含字母、数字、中文、下划线和连字符'),
    
  body('email')
    .isEmail()
    .withMessage('请输入有效的邮箱地址')
    .normalizeEmail(),
    
  body('password')
    .isLength({ min: 6 })
    .withMessage('密码长度至少6个字符')
    .matches(/^(?=.*[a-zA-Z])(?=.*\d)/)
    .withMessage('密码必须包含至少一个字母和一个数字'),
    
  body('phone')
    .optional()
    .matches(/^[\+]?[1-9][\d]{0,15}$/)
    .withMessage('请输入有效的手机号码'),
    
  body('role')
    .isIn(['farmer', 'logistics', 'merchant', 'consumer'])
    .withMessage('角色必须是: farmer, logistics, merchant, consumer 之一'),
    
  body('profile.name')
    .optional()
    .trim()
    .isLength({ max: 100 })
    .withMessage('姓名长度不能超过100个字符'),
    
  body('profile.location')
    .optional()
    .trim()
    .isLength({ max: 200 })
    .withMessage('地址长度不能超过200个字符'),
    
  handleValidationErrors
];

/**
 * 用户登录验证规则
 */
const validateUserLogin = [
  body('email')
    .isEmail()
    .withMessage('请输入有效的邮箱地址')
    .normalizeEmail(),
    
  body('password')
    .notEmpty()
    .withMessage('密码不能为空'),
    
  handleValidationErrors
];

/**
 * 茶叶批次创建验证规则
 */
const validateBatchCreation = [
  body('name')
    .trim()
    .isLength({ min: 1, max: 100 })
    .withMessage('茶叶名称长度必须在1-100个字符之间'),
    
  body('variety')
    .trim()
    .isLength({ min: 1, max: 50 })
    .withMessage('茶叶品种长度必须在1-50个字符之间'),
    
  body('grade')
    .optional()
    .isIn(['特级', '一级', '二级', '三级', '其他'])
    .withMessage('茶叶等级必须是: 特级, 一级, 二级, 三级, 其他 之一'),
    
  body('description')
    .optional()
    .trim()
    .isLength({ max: 1000 })
    .withMessage('描述长度不能超过1000个字符'),
    
  body('production.origin.province')
    .trim()
    .isLength({ min: 1, max: 50 })
    .withMessage('省份长度必须在1-50个字符之间'),
    
  body('production.origin.city')
    .trim()
    .isLength({ min: 1, max: 50 })
    .withMessage('城市长度必须在1-50个字符之间'),
    
  body('production.origin.county')
    .optional()
    .trim()
    .isLength({ max: 50 })
    .withMessage('县区长度不能超过50个字符'),
    
  body('production.origin.coordinates.latitude')
    .optional()
    .isFloat({ min: -90, max: 90 })
    .withMessage('纬度必须在-90到90之间'),
    
  body('production.origin.coordinates.longitude')
    .optional()
    .isFloat({ min: -180, max: 180 })
    .withMessage('经度必须在-180到180之间'),
    
  body('production.harvestDate')
    .isISO8601()
    .withMessage('采摘日期格式无效')
    .custom((value) => {
      const date = new Date(value);
      const now = new Date();
      if (date > now) {
        throw new Error('采摘日期不能是未来时间');
      }
      return true;
    }),
    
  body('production.processingMethod')
    .optional()
    .trim()
    .isLength({ max: 200 })
    .withMessage('加工工艺描述不能超过200个字符'),
    
  handleValidationErrors
];

/**
 * 物流记录验证规则
 */
const validateLogisticsRecord = [
  param('batchId')
    .matches(/^[A-Z0-9]{10,20}$/)
    .withMessage('批次ID格式无效'),
    
  body('stage')
    .isIn(['pickup', 'transit', 'warehouse', 'delivery'])
    .withMessage('物流阶段必须是: pickup, transit, warehouse, delivery 之一'),
    
  body('location.address')
    .trim()
    .isLength({ min: 1, max: 200 })
    .withMessage('地址长度必须在1-200个字符之间'),
    
  body('startTime')
    .isISO8601()
    .withMessage('开始时间格式无效')
    .custom((value) => {
      const date = new Date(value);
      const now = new Date();
      if (date > now) {
        throw new Error('开始时间不能是未来时间');
      }
      return true;
    }),
    
  body('endTime')
    .optional()
    .isISO8601()
    .withMessage('结束时间格式无效')
    .custom((value, { req }) => {
      if (value) {
        const endTime = new Date(value);
        const startTime = new Date(req.body.startTime);
        if (endTime < startTime) {
          throw new Error('结束时间不能早于开始时间');
        }
      }
      return true;
    }),
    
  body('temperature.min')
    .optional()
    .isNumeric()
    .withMessage('最低温度必须是数字'),
    
  body('temperature.max')
    .optional()
    .isNumeric()
    .withMessage('最高温度必须是数字'),
    
  body('vehicle.type')
    .optional()
    .trim()
    .isLength({ max: 50 })
    .withMessage('车辆类型长度不能超过50个字符'),
    
  body('notes')
    .optional()
    .trim()
    .isLength({ max: 500 })
    .withMessage('备注长度不能超过500个字符'),
    
  handleValidationErrors
];

/**
 * 销售记录验证规则
 */
const validateSalesRecord = [
  param('batchId')
    .matches(/^[A-Z0-9]{10,20}$/)
    .withMessage('批次ID格式无效'),
    
  body('storeInfo.storeName')
    .trim()
    .isLength({ min: 1, max: 100 })
    .withMessage('店铺名称长度必须在1-100个字符之间'),
    
  body('storeInfo.storeAddress')
    .trim()
    .isLength({ min: 1, max: 200 })
    .withMessage('店铺地址长度必须在1-200个字符之间'),
    
  body('storeInfo.storeType')
    .isIn(['physical', 'online'])
    .withMessage('店铺类型必须是: physical, online 之一'),
    
  body('receiveDate')
    .isISO8601()
    .withMessage('入库日期格式无效')
    .custom((value) => {
      const date = new Date(value);
      const now = new Date();
      if (date > now) {
        throw new Error('入库日期不能是未来时间');
      }
      return true;
    }),
    
  body('sellDate')
    .optional()
    .isISO8601()
    .withMessage('销售日期格式无效')
    .custom((value, { req }) => {
      if (value) {
        const sellDate = new Date(value);
        const receiveDate = new Date(req.body.receiveDate);
        if (sellDate < receiveDate) {
          throw new Error('销售日期不能早于入库日期');
        }
      }
      return true;
    }),
    
  body('price.retail')
    .isNumeric()
    .custom((value) => {
      if (parseFloat(value) < 0) {
        throw new Error('零售价格不能为负数');
      }
      return true;
    })
    .withMessage('请输入有效的零售价格'),
    
  body('quantity.received')
    .isInt({ min: 1 })
    .withMessage('入库数量必须是大于0的整数'),
    
  body('quantity.sold')
    .optional()
    .isInt({ min: 0 })
    .withMessage('销售数量必须是非负整数')
    .custom((value, { req }) => {
      if (value && parseInt(value) > parseInt(req.body.quantity.received)) {
        throw new Error('销售数量不能超过入库数量');
      }
      return true;
    }),
    
  handleValidationErrors
];

/**
 * 分页参数验证规则
 */
const validatePagination = [
  query('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('页码必须是大于0的整数')
    .toInt(),
    
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('每页数量必须是1-100之间的整数')
    .toInt(),
    
  handleValidationErrors
];

/**
 * MongoDB ObjectId验证规则
 */
const validateObjectId = (paramName) => [
  param(paramName)
    .isMongoId()
    .withMessage(`${paramName}格式无效`),
    
  handleValidationErrors
];

/**
 * 搜索参数验证规则
 */
const validateSearch = [
  query('keyword')
    .optional()
    .trim()
    .isLength({ min: 1, max: 100 })
    .withMessage('搜索关键词长度必须在1-100个字符之间'),
    
  query('status')
    .optional()
    .isIn(['created', 'production', 'logistics', 'sales', 'consumed'])
    .withMessage('状态参数无效'),
    
  query('variety')
    .optional()
    .trim()
    .isLength({ max: 50 })
    .withMessage('品种参数长度不能超过50个字符'),
    
  query('startDate')
    .optional()
    .isISO8601()
    .withMessage('开始日期格式无效'),
    
  query('endDate')
    .optional()
    .isISO8601()
    .withMessage('结束日期格式无效')
    .custom((value, { req }) => {
      if (value && req.query.startDate) {
        const endDate = new Date(value);
        const startDate = new Date(req.query.startDate);
        if (endDate < startDate) {
          throw new Error('结束日期不能早于开始日期');
        }
      }
      return true;
    }),
    
  handleValidationErrors
];

module.exports = {
  handleValidationErrors,
  validateUserRegistration,
  validateUserLogin,
  validateBatchCreation,
  validateLogisticsRecord,
  validateSalesRecord,
  validatePagination,
  validateObjectId,
  validateSearch
};